package frameTools;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.jnetpcap.Pcap;
import org.jnetpcap.PcapIf;

/**
 * This class is designed to exercise the functionality necessary to read IP
 * frames off of a local interface for the purposes of transmitting them to
 * various other clients on a local network.
 * 
 * References: http://jnetpcap.com/download, http://jnetpcap.com/eclipse
 * http://www.winpcap.org/default.htm
 * 
 * Tested Using: jnetpcap-1.3.0-1.win64, WinPcap_4_1_2
 * 
 */
public class FrameReader {

	StringBuilder     errbuf = new StringBuilder();
	List<PcapIf>      ifs    = new ArrayList<PcapIf>();
	PcapIf 		      device;
	Pcap 		      pcap;
	FrameReaderThread reader;
	
	
	public FrameReader() throws InterruptedException {
		findInterfaces();
		openDevice(0);
		reader = new FrameReaderThread(pcap, 10);
		reader.start();
	}
	
	/**
	 * Find interfaces
	 */
	private void findInterfaces() {
		System.out.println("Finding available devices....");
		// Construct a list of local interfaces
		int statusCode = Pcap.findAllDevs(ifs, errbuf);
		if (statusCode != Pcap.OK) {
			System.out.println("Error occurred: " + errbuf.toString());
			return;
		}
	}

	/**
	 * Print the found interfaces
	 */
	public void printInterfaces() {
		// We have a list of PcapIf devices to work with now.
		Iterator<PcapIf> iter = ifs.iterator();
		while (iter.hasNext()) {
			PcapIf next = iter.next();
			System.out.println(next.getDescription() + "\n"
					+ next.getAddresses() + "\n\n");
		}
	}
	
	/**
	 * Open a device/interface found during findInterfaces()
	 * 
	 * @param dev
	 */
	public void openDevice(int dev) {
		// TODO: 1st device won't always be the one we want, parameterize?
		device = ifs.get(dev);
		System.out.print("Using first available device...");
		System.out.println((device.getDescription() != null) ? device
				.getDescription() : device.getName());

		/**
		 * Open desired interface for listening
		 */
		int snaplen = 64 * 1024; // Capture all packets, no trucation
		int flags = Pcap.MODE_PROMISCUOUS; // capture all packets
		int timeout = 10 * 1000; // 10 seconds in millis
		pcap = Pcap.openLive(device.getName(), snaplen, flags, timeout,
				errbuf);
		if (pcap == null) {
			System.out.println("Error opening device for capture: "
					+ errbuf.toString());
			return;
		}
	}
}
